package com.store.orm.mongo.curd.impl;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.store.orm.mongo.curd.Delete;
import com.store.orm.mongo.curd.MongoUtil;
import com.store.orm.util.JsonUtil;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;

/**
 * @author 宫静雨
 * @version 1.0
 */
public class MongoDelete implements Delete {
    private MongoDatabase database ;
    private static final MongoUtil util = new MongoUtil();

    public MongoDelete(MongoDatabase database) {
        this.database = database;
    }

    private <T> Bson helpT(T t) {
        try {
            LinkedHashMap<String, Object> map = util.parseTToMap(t);
            LinkedHashMap<String, Object> cascade = util.cascade(map);
            List<Bson> list = new ArrayList<>();
            cascade.forEach((k, v) -> list.add(eq(k, v)));
            return and(list);
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    private Bson helpJson(String json) {
        LinkedHashMap<String, Object> map = JsonUtil.parse(json);
        conversionId(map);
        LinkedHashMap<String, Object> cascade = util.cascade(map);
        List<Bson> list = new ArrayList<>();
        cascade.forEach((k, v) -> list.add(eq(k, v)));
        return and(list);
    }

    private void conversionId(LinkedHashMap<String, Object> map) {
        if (map.containsKey("id")) {
            Object id = map.get("id");
            map.remove("id");
            map.put("_id", id);
        }
    }

    private Bson helpMap(LinkedHashMap<String, Object> map) {
        conversionId(map);
        LinkedHashMap<String, Object> cascade = util.cascade(map);
        List<Bson> list = new ArrayList<>();
        cascade.forEach((k, v) -> list.add(eq(k, v)));
        return and(list);
    }

    @Override
    public <T> void delete(T t) {
        MongoCollection<Document> collection = database.getCollection(util.collection(t.getClass()));
        collection.deleteOne(helpT(t));
    }

    @Override
    public <T> void deleteMany(T t) {
        MongoCollection<Document> collection = database.getCollection(util.collection(t.getClass()));
        collection.deleteMany(helpT(t));
    }

    @Override
    public void delete(Class<?> cls, String json) {
        MongoCollection<Document> collection = database.getCollection(util.collection(cls));
        collection.deleteOne(helpJson(json));
    }

    @Override
    public void deleteMany(Class<?> cls, String json) {
        MongoCollection<Document> collection = database.getCollection(util.collection(cls));
        collection.deleteMany(helpJson(json));
    }

    @Override
    public void delete(Class<?> cls, LinkedHashMap<String, Object> map) {
        MongoCollection<Document> collection = database.getCollection(util.collection(cls));
        collection.deleteOne(helpMap(map));
    }

    @Override
    public void deleteMany(Class<?> cls, LinkedHashMap<String, Object> map) {
        MongoCollection<Document> collection = database.getCollection(util.collection(cls));
        collection.deleteMany(helpMap(map));
    }

    @Override
    public void delete(Class<?> cls, Bson filter) {
        MongoCollection<Document> collection = database.getCollection(util.collection(cls));
        collection.deleteOne(filter);
    }

    @Override
    public void deleteMany(Class<?> cls, Bson filter) {
        MongoCollection<Document> collection = database.getCollection(util.collection(cls));
        collection.deleteMany(filter);
    }
}